package com.quantum.service
{


	import com.quantum.collection.Map;

	import flash.utils.getQualifiedClassName;

	import mx.collections.ArrayCollection;

	public class ServiceRegistry
	{
		private static var _instance:ServiceRegistry;

		private static var _instances:Map=null; //=new MapProvider();

		private var services:Map=null; //=new MapProvider();

		private var filters:Map=null; //=new MapProvider();

		public function ServiceRegistry(singletonToken:SingletonToken)
		{
		}

		/**
		 * 获取KernelManager实例，当参数domain为null时返回defaultInstance
		 * @param domain 不同特例的实现
		 *
		 */
		public static function getInstance(domain:Object=null):ServiceRegistry
		{
			if (null == domain)
			{
				if (_instance == null)
				{
					_instance=new ServiceRegistry(new SingletonToken());
				}
				return _instance;
			}

			domain=formatKey(domain); //构造key值

			var value:Object=_instances.getObject(domain);
			if (value == null)
			{
				var instance:ServiceRegistry=new ServiceRegistry(new SingletonToken());
				_instances.put(domain, instance);
				return instance;
			}
			else
			{
				return value as ServiceRegistry;
			}
		}



		/**
		 *
		 * 获取与某特定实例及上下文环境的Service
		 * <br>含有过滤功能
		 *
		 */
		public function getService(key:Object=null, context:Object=null, priority:uint=0):Object
		{
			var list:ArrayCollection=getValueAsArrayCollection(this.services, key);
			list=filter(list, key, context);
			if (list != null && list.length > 0)
			{
				var index:uint=0;
				for (var i:uint; i < list.length; i++)
				{
					var object:Object=list.getItemAt(i);
					if (!(object is Priority) || (object as Priority).priority < priority)
					{
						index=(i == 0) ? i : (i - 1);
						break;
					}
				}
				return list.getItemAt(index);
			}
			return null;
		}

		/**
		 * 获取与某特定实例及上下文环境的Service组合
		 * <br>含有过滤功能
		 *
		 */
		public function getServices(key:Object=null, context:Object=null):ArrayCollection
		{
			var list:ArrayCollection=getValueAsArrayCollection(this.services, key);
			list=filter(list, key, context);
			if (list != null)
			{
				return new ArrayCollection(list.source.concat());
			}
			return new ArrayCollection();
		}


		public function registerService(service:Object, key:Object=null):void
		{
			if (service == null)
			{
				return;
			}
			var list:ArrayCollection=getValueAsArrayCollection(this.services, key);
			if (list != null)
			{
				doRegisterService(list, service);

			}
		}

		/**
		 *
		 * 注册过程中增加优先级处理
		 *
		 */
		private function doRegisterService(list:ArrayCollection, service:Object):void
		{
			if (!(service is Priority))
			{
				list.addItem(service);
				return;
			}
			var servicePriority:uint=(service as Priority).priority;
			if (0 == servicePriority)
			{
				list.addItem(service);
				return;
			}

			var index:uint=0;
			for (var i:uint; i < list.length; i++)
			{
				var object:Object=list.getItemAt(i);
				if (!(object is Priority) || (object as Priority).priority < servicePriority)
				{
					index=i;
					break;
				}
			}
			list.addItemAt(service, index); //按照优先级插入
		}

		public function registerFilter(filter:Filter, key:Object=null):void
		{
			if (filter == null)
			{
				return;
			}
			var list:ArrayCollection=getValueAsArrayCollection(this.filters, key);
			if (list != null)
			{
				list.addItem(filter);
			}
		}

		public function getFilters(key:Object=null):Array
		{
			var list:ArrayCollection=getValueAsArrayCollection(this.filters, key);
			if (list != null)
			{
				return list.source.concat();
			}
			return [];
		}

		public function clearFilters(key:Object=null):Array
		{
			var list:ArrayCollection=getValueAsArrayCollection(this.filters, key);
			if (list != null && list.length > 0)
			{
				var result:Array=list.source.concat();
				list.removeAll();
				return result; //返回被清空的过滤器集合
			}
			return [];
		}


		/**
		 * 过滤service集合
		 *
		 *
		 */
		private function filter(serviceList:ArrayCollection, value:Object=null, context:Object=null):ArrayCollection
		{
			if (serviceList == null || serviceList.length <= 0)
			{
				return serviceList; //集合没有元素不过滤
			}
			var filterList:ArrayCollection=getValueAsArrayCollection(this.filters, value);
			if (filterList.length > 0)
			{
				var result:ArrayCollection=new ArrayCollection;
				for each (var service:Object in serviceList)
				{
					var flag:Boolean=true;
					for each (var filter:Filter in filterList)
					{
						if (!filter.filter(service, value, context))
						{
							flag=false;
							break;
						}
					}
					if (flag)
					{
						result.addItem(service);
					}
				}
				return result;
			}
			return serviceList;
		}


		private static function getValueAsArrayCollection(provider:Map, key:Object):ArrayCollection
		{
			if (key == null)
			{
				key=new Object();
			}
			key=formatKey(key);
			var value:Object=provider.getObject(key);
			if (null == value)
			{
				var list:ArrayCollection=new ArrayCollection();
				provider.put(key, list);
				return list;
			}
			else
			{
				if (value is ArrayCollection)
				{
					return value as ArrayCollection;
				}
				else
				{
					//should never occurs
				}
			}
			return new ArrayCollection();
		}

		/**
		 * 这里使用对象的类的签名，如果直接传入String类型则视为类签名
		 *
		 *
		 */
		private static function formatKey(key:Object):String
		{
			if (key is String)
			{
				return key as String;
			}
			else
			{
				return getQualifiedClassName(key);
			}
		}
	}
}


class SingletonToken
{
}